package test.workload;



import java.util.ArrayList;
import java.util.List;

import test.envset.GlobalState;
import test.envset.GlobalState;
import test.log.SqlLog;
import test.stat.StatError;
import test.stat.StatExecTime;
import test.stat.Statictics;

import test.utility.Utility;

/*@ 2023-07-05
        观察线程
        */
public class ObserverWorker implements Runnable {
    private static int SHOW_INTERVAL_SEC = 60;
    List<Worker> workers = null;
    boolean terminateFlag = false;
    SqlLog logFresh = null;

    public ObserverWorker() {
    }

    //    addWorker(Worker worker)方法，用于向workers列表中添加工作线程。
//    如果workers列表为空，先创建一个新的ArrayList对象。然后将传入的工作线程对象添加到列表中。
    public synchronized void addWorker(Worker worker) {
        if (workers == null) {
            workers = new ArrayList<Worker>();
        }
        workers.add(worker);
    }

    public void finish() {
        terminateFlag = true;
    }

    //    showInfo()方法，用于展示工作线程的执行信息。
//    该方法会遍历workers列表，获取每个工作线程的计数器，并进行累加。
//    然后将统计信息拼接到info字符串中，并输出。最后，如果终止标志为false，则刷新SQL日志和统计信息。
    public void showInfo() {
        long[] cnt = {0, 0, 0};
        StringBuilder info = new StringBuilder();
        info.append(String.format("--%s\n", Utility.CurrentTime()));
        for (Worker worker : workers) {
            long[] counter = worker.getCounter();
            cnt[0] += counter[0];
            cnt[1] += counter[1];
            cnt[2] += counter[2];
            info.append(String.format("--thread%d: count=%d, succ=%d, fail=%d,rate=%.2f%%\n",
                    worker.getThreadID(), counter[0], counter[1], counter[2],
                    counter[0] == 0 ? 0 : counter[1] * 100.0 / counter[0]));
        }
        info.append(String.format("--TOTAL:_count=%d, succ=%d, fail=%d, rate=%.2f%%\n", cnt[0], cnt[1], cnt[2], cnt[0] == 0 ? 0 : cnt[1] * 100.0 / cnt[0]));
        Utility.output(info.toString());
        if (!GlobalState.getTerminateFlag()) {
            logRefresh();
            statRefresh();
        }
    }

    @Override
    public void run() {
        try {
            Thread.sleep(5000);
            do {
                showInfo();
                Thread.sleep(1000 * SHOW_INTERVAL_SEC);
            } while (!terminateFlag);
        } catch (InterruptedException e) {
        }
    }

    //仅当不保存日志时，才每隔一段时间强行刷新sql日志
//防止中途因为某些原因导致测试程序中断或者dmserver卡住，无法获取最新的日志
    private void logRefresh() {
        int saveFlag = GlobalState.getGenSaveFlag();
        if (saveFlag != 0) {
            return;
        }
        if (logFresh == null) {
            logFresh = new SqlLog(GlobalState.getLogPre() + "-refresh", "sql");
        } else {

            logFresh.reOpen();
        }
        for (Worker worker : workers) {
            worker.logFlush(logFresh);
        }
        logFresh.Close();
    }

    //统计信息刷新
    private void statRefresh() {
        statExecTimeRefresh();
        statErrorRefresh();
    }

    private void statExecTimeRefresh() {
        if (workers.get(0) instanceof RunWorker){
            return;
        }

        if (!GlobalState.getExecFlag()) { //不执行sql就不进行执行时间统计
            return;
        }
        StatExecTime stat = new StatExecTime();
        List<Statictics> stats = new ArrayList<Statictics>();
        for (Worker worker : workers) {
            stats.add(((GenWorker) worker).getStatExecTime());
        }
        stat.combine(stats);
        SqlLog statTimeLog = new SqlLog(GlobalState.getLogPre() + "-time", "log");
        stat.output(statTimeLog);
        statTimeLog.Close();
    }

    private void statErrorRefresh() {
        if (workers.get(0) instanceof RunWorker){
            return;
        }

        if (!GlobalState.getExecFlag()) { //不执行sql就不进行执行时间统计
            return;
        }
        StatError stat = new StatError();
        List<Statictics> stats = new ArrayList<Statictics>();
        for (Worker worker : workers) {
            stats.add(((GenWorker) worker).getStatError());
        }
            stat.combine(stats);
            SqlLog statErrorLog = new SqlLog(GlobalState.getLogPre() + "-err","log");
            stat.output(statErrorLog);
            statErrorLog.Close();
    }

}
